#include <lpc2292.h>
#include <KeyBoard_driver.h>
#include <Defs.h>

static uint delay;
static uint pressed;
static byte _key;
static byte _keyCode;

static const byte keys[4][4] =	{	
	{'1', '2', '3', 'A'},	//	0..3
	{'4', '5', '6', 'B'},	//	4..7
	{'7', '8', '9', 'C'},	//	8..11
	{'*', '0', '#', 'D'}};	//	12..15


uint checkColumns(uint set, uint clr)
{
	uint i;
	
	IO2SET	|=	set;
	IO2CLR	|=	clr;
	
	for(i = 0; i < 10; ++i);
	
	return ~IO2PIN & (P_27 | P_26 | P_25 | P_24);
}

uint getRow(uint row)
{
	if(row & 0x1000000) 
		return 0;
	if(row & 0x2000000) 
		return 1;
	if(row & 0x4000000) 
		return 2;
	if(row & 0x8000000) 
		return 3;
	return -1;
}

uint cutRow(uint row)
{
	if(row & 0x1000000) 
		return row = 0x1000000;
	if(row & 0x2000000) 
		return row = 0x2000000;
	if(row & 0x4000000) 
		return row = 0x4000000;
	if(row & 0x8000000) 
		return row = 0x8000000;
	return -1;
}

//Keyboard polling
byte pollKB(void)
{
	uint row = 0;

	IO2DIR	|=	P_19 | P_18 | P_17 | P_16;					//Columns - on output
	IO2DIR	&=	~(P_27 | P_26 | P_25 | P_24);				//Rows - on input

	pressed	= checkColumns(0, P_19 | P_18 | P_17 | P_16);
	
	if(pressed && (delay < PRESS_DELAY_MS))
	{
		++delay;
		return KB_NOT_PRESSED;
	}

	if(pressed)
	{
		delay =	0;	
		row	= cutRow(pressed);	

		if(!(row + 1))
				return KB_ERROR;
		
		if(row & checkColumns(P_19 | P_18 | P_17, P_16))				//col	=	0;
			return ((getRow(row) << 2) | 0);
		
		if(row & checkColumns(P_19 | P_18 | P_16, P_17))				//col	=	1;
			return ((getRow(row) << 2) | 1);

		if(row & checkColumns(P_19 | P_17 | P_16, P_18))				//col	=	2;
			return ((getRow(row) << 2) | 2);
		
		if(row & checkColumns(P_18 | P_17 | P_16, P_19))				//col	=	3;
			return ((getRow(row) << 2) | 3);
	
		return KB_ERROR;
	}
	else
	{
		delay = PRESS_DELAY_MS;	
		return KB_NOT_PRESSED;
	}
}

//Read key from keyboard
byte readKey(void) 
{
	_keyCode = pollKB();
	
	if(_keyCode < KB_ERROR)
	{
		_key = keys[(_keyCode & 0xC) >> 2][_keyCode & 0x3];
	
		return _key;
	}
	else 
		return KB_NOT_PRESSED;
}

//Key is pressed
byte keyPressed(void)
{
	if(_keyCode < KB_ERROR)
		return 1;
	else 
		return 0;
}

//Get key char
byte key(void)
{
	return _key;
}

//Get key code
byte keyCode(void)
{
	return _keyCode;
}